package com.simpou.tests.persistence;

import com.simpou.commons.model.entity.BaseEntity;
import com.simpou.commons.persistence.common.Transaction;
import com.simpou.commons.persistence.dao.BasicDAO;
import com.simpou.commons.utils.file.FileHelper;
import com.simpou.commons.utils.file.PropertyHelper;
import com.simpou.commons.utils.file.filter.ExtensionFileNameFilter;
import com.simpou.commons.utils.file.filter.FileNameFilters;
import com.simpou.commons.utils.file.filter.SubDirectoryFileNameFilter;
import com.simpou.commons.utils.lang.Randoms;
import com.simpou.tests.commons.exception.TestFailedError;

import java.util.ArrayList;
import java.util.List;

/**
 * @author jonas1
 * @version 19/09/13
 * @since 19/09/13
 */
public class TesterHelper {

    private static List<Class<?>> ENTITIES;

    //TODO usar pu pra escanear
    @Deprecated
    public static List<Class<?>> scanEntities(final String puName, final String pkgName) {
        if (ENTITIES != null) {
            return ENTITIES;
        }

        FileNameFilters fileFilter = new FileNameFilters(
                new ExtensionFileNameFilter("java"),
                new SubDirectoryFileNameFilter(true, pkgName.split("\\.")));
        List<String> fileList = FileHelper.list(PropertyHelper.getWorkDir(), true, fileFilter);
        List<Class<?>> classes = new ArrayList<Class<?>>();
        if (fileList.isEmpty()) {
            throw new TestFailedError("No entities found.");
        } else {
            final String pkgPath = pkgName.replaceAll("\\.", "/");
            for (String filePath : fileList) {
                final String filePathNormalized = FileHelper.normalizeFilePathDelim(filePath);
                int startPkgIndex = filePathNormalized.indexOf(pkgPath);
                String className = filePathNormalized.substring(startPkgIndex, filePathNormalized.length() - 5).replaceAll("/", "\\.");
                try {
                    Class<?> clasz = Class.forName(className);
                    classes.add(clasz);
                } catch (ClassNotFoundException ex) {
                }
            }
            if (classes.isEmpty()) {
                throw new TestFailedError("No entities found.");
            } else {
                ENTITIES = classes;
            }
        }
        return ENTITIES;
    }

    /**
     * Persiste aleatoriamente entidades. O número de entidades a serem criadas
     * é definido aleatoriamente mas limitado segundo anotação
     * "RandomFillableConfig". Caso anotação não seja definida podem ser geradas
     * qualquer número de entidades entre 5 e 25.
     *
     * @param entityClass Classe da entidade. Usada para gerar novas instâncias
     *                    via reflexão.
     * @param dao         Para realizar as operações DAO necessárias.
     * @param <T>         a T object.
     * @return Exceções ocorridas durante o processo se houverem. Valor não
     *         null.
     * @throws java.lang.Exception Erros não associados ao crud se houverem.
     * @see com.simpou.commons.utils.lang.annot.RandomFillableConfig
     */
    public static <T extends BaseEntity> List<Exception> fillRandom(
            final Class<T> entityClass, final BasicDAO dao)
            throws Exception {
        final List<Exception> exceptions = new ArrayList<Exception>();

        final List<T> list = Randoms.getList(entityClass);

        // gera entidades
        final Transaction tx = dao.getTransaction();
        for (T entity : list) {
            tx.begin();
            try {
                dao.update(entity);
                tx.commit();
            } catch (Exception ex) {
                exceptions.add(ex);
                if (tx.isActive()) {
                    tx.rollback();
                }
            }
        }

        return exceptions;
    }
}
